using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Caching;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;
using Volo.Abp.MultiTenancy;
using Volo.Abp.EntityFrameworkCore;
using UserManagementService.HttpApi.Host.HealthChecks;

namespace UserManagementService
{
    [DependsOn(
        typeof(AbpAspNetCoreMvcModule),
        typeof(AbpAutofacModule),
        typeof(AbpCachingStackExchangeRedisModule),
        typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
        typeof(AbpAspNetCoreSerilogModule),
        typeof(AbpSwashbuckleModule),
        typeof(AbpEntityFrameworkCoreModule),
        typeof(UserManagementServiceHttpApiModule),
        typeof(UserManagementServiceApplicationModule),
        typeof(UserManagementServiceEntityFrameworkCoreModule)
    )]
    public class UserManagementServiceHttpApiHostModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var configuration = context.Services.GetConfiguration();
            var hostingEnvironment = context.Services.GetHostingEnvironment();

            ConfigureCache(configuration);
            ConfigureDataProtection(context, configuration, hostingEnvironment);
            ConfigureCors(context, configuration);
            ConfigureAuthentication(context, configuration);
            ConfigureSwagger(context, configuration);
            ConfigureHealthChecks(context);
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseCorrelationId();
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCors();
            app.UseAuthentication();

            if (MultiTenancyConsts.IsEnabled)
            {
                app.UseMultiTenancy();
            }

            app.UseAbpRequestLocalization();
            app.UseAuthorization();
            app.UseSwagger();
            app.UseAbpSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "UserManagementService API");
            });

            app.UseAuditing();
            app.UseUnitOfWork();
            app.UseConfiguredEndpoints();

            if (env.IsDevelopment())
            {
                app.UseAbpSerilogEnrichers();
            }
        }

        private void ConfigureCache(IConfiguration configuration)
        {
            Configure<AbpDistributedCacheOptions>(options =>
            {
                options.KeyPrefix = "UserManagementService:";
            });
        }

        private void ConfigureDataProtection(
            ServiceConfigurationContext context,
            IConfiguration configuration,
            IWebHostEnvironment hostingEnvironment)
        {
            var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("UserManagementService");

            if (hostingEnvironment.IsDevelopment())
            {
                dataProtectionBuilder.PersistKeysToFileSystem(Path.Combine(hostingEnvironment.ContentRootPath, "temp-keys"));
            }
        }

        private void ConfigureCors(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(builder =>
                {
                    builder
                        .WithOrigins(configuration["App:CorsOrigins"]?
                            .Split(",", StringSplitOptions.RemoveEmptyEntries)
                            .Select(o => o.RemovePostFix("/"))
                            .ToArray() ?? new[] { "*" })
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });
        }

        private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAuthentication("Bearer")
                .AddJwtBearer(options =>
                {
                    options.Authority = "http://localhost:8080/realms/master";
                    options.Audience = "user-management-service";
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidIssuer = "http://localhost:8080/realms/master",
                        ValidateAudience = true,
                        ValidAudience = "user-management-service",
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true
                    };
                });
        }

        private void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration)
        {
            context.Services.AddAbpSwaggerGenWithOAuth(
                configuration["AuthServer:Authority"] ?? "https://localhost:44310",
                new Dictionary<string, string>
                {
                    { "UserManagementService", "用户管理服务 API" }
                },
                options =>
                {
                    options.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
                    {
                        Title = "UserManagementService API",
                        Version = "v1",
                        Description = "Matrix Framework 用户管理服务 RESTful API"
                    });

                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                });
        }

        private void ConfigureHealthChecks(ServiceConfigurationContext context)
        {
            context.Services.AddHealthChecks()
                .AddCheck<UserManagementHealthCheck>("user-management-service")
                .AddCheck("database", () =>
                {
                    // TODO: 实现实际的数据库连接检查
                    return Task.FromResult(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("数据库连接正常"));
                })
                .AddCheck("redis", () =>
                {
                    // TODO: 实现实际的Redis连接检查
                    return Task.FromResult(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("Redis连接正常"));
                })
                .AddCheck("keycloak", () =>
                {
                    // TODO: 实现实际的Keycloak连接检查
                    return Task.FromResult(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy("Keycloak连接正常"));
                })
                .AddCheck("memory", () =>
                {
                    var memoryUsage = GC.GetTotalMemory(false) / 1024 / 1024; // MB
                    if (memoryUsage > 1000) // 超过1GB
                    {
                        return Task.FromResult(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Degraded($"内存使用较高: {memoryUsage}MB"));
                    }
                    return Task.FromResult(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult.Healthy($"内存使用正常: {memoryUsage}MB"));
                });
        }
    }
}